/**
 * 认证服务
 * 处理用户认证相关的API调用和本地存储
 */

import api from './api';
import { storage } from '../utils';
import { requestGuard } from '../utils/requestGuard';
import { 
  LoginRequest, 
  LoginResponse, 
  RegisterRequest, 
  RegisterResponse,
  ChangePasswordRequest,
  ResetPasswordRequest,
  TokenRefreshRequest,
  TokenResponse,
  UserProfile,
  Token,
  AUTH_STORAGE_KEYS
} from '../types/auth';
import { showNotification } from '../utils/notification';

class AuthService {
  private tokenRefreshPromise: Promise<string> | null = null;

  /**
   * 用户登录
   */
  async login(loginData: LoginRequest): Promise<LoginResponse> {
    try {
      const response = await api.post<LoginResponse>('/v1/auth/login', loginData);
      const result = response.data.data;
      
      // 保存认证信息到本地存储
      this.saveAuthData(result);
      
      showNotification('success', '登录成功', `欢迎回来，${result.user.full_name || result.user.username}！`);
      return result;
    } catch (error: any) {
      const message = error.response?.data?.message || '登录失败';
      showNotification('error', '登录失败', message);
      throw error;
    }
  }

  /**
   * 用户注册
   */
  async register(registerData: RegisterRequest): Promise<RegisterResponse> {
    try {
      const response = await api.post<RegisterResponse>('/v1/auth/register', registerData);
      const result = response.data.data;
      
      showNotification('success', '注册成功', result.message);
      return result;
    } catch (error: any) {
      const message = error.response?.data?.message || '注册失败';
      showNotification('error', '注册失败', message);
      throw error;
    }
  }

  /**
   * 用户登出
   */
  async logout(): Promise<void> {
    try {
      await api.post('/v1/auth/logout');
    } catch (error) {
      console.warn('登出请求失败:', error);
    } finally {
      // 无论请求是否成功，都清除本地存储
      this.clearAuthData();
      showNotification('info', '已登出', '您已成功登出系统');
    }
  }

  /**
   * 刷新访问令牌
   */
  async refreshToken(): Promise<string> {
    // 防止并发刷新
    if (this.tokenRefreshPromise) {
      return this.tokenRefreshPromise;
    }

    this.tokenRefreshPromise = this.performTokenRefresh();
    
    try {
      const newToken = await this.tokenRefreshPromise;
      return newToken;
    } finally {
      this.tokenRefreshPromise = null;
    }
  }

  private async performTokenRefresh(): Promise<string> {
    const refreshToken = this.getRefreshToken();
    
    if (!refreshToken) {
      throw new Error('No refresh token available');
    }

    try {
      const response = await api.post<TokenResponse>('/v1/auth/refresh', {
        refresh_token: refreshToken
      });
      
      const tokenData = response.data.data;
      
      // 更新本地存储的令牌
      this.updateToken({
        access_token: tokenData.access_token,
        refresh_token: tokenData.refresh_token || refreshToken,
        token_type: tokenData.token_type,
        expires_in: tokenData.expires_in,
        expires_at: Date.now() + tokenData.expires_in * 1000
      });
      
      return tokenData.access_token;
    } catch (error) {
      // 刷新失败，清除认证信息
      this.clearAuthData();
      throw error;
    }
  }

  /**
   * 修改密码
   */
  async changePassword(passwordData: ChangePasswordRequest): Promise<void> {
    try {
      await api.post('/v1/auth/change-password', passwordData);
      showNotification('success', '密码修改成功', '您的密码已成功修改');
    } catch (error: any) {
      const message = error.response?.data?.message || '密码修改失败';
      showNotification('error', '密码修改失败', message);
      throw error;
    }
  }

  /**
   * 重置密码
   */
  async resetPassword(resetData: ResetPasswordRequest): Promise<void> {
    try {
      await api.post('/v1/auth/reset-password', resetData);
      showNotification('success', '重置邮件已发送', '请检查您的邮箱并按照说明重置密码');
    } catch (error: any) {
      const message = error.response?.data?.message || '重置密码失败';
      showNotification('error', '重置密码失败', message);
      throw error;
    }
  }

  /**
   * 获取当前用户信息 - 使用requestGuard防止重复请求
   */
  async getCurrentUser(): Promise<UserProfile> {
    // 使用requestGuard防止重复请求
    if (!requestGuard.canRequest('getCurrentUser')) {
      // 如果请求被阻止，尝试从本地存储获取用户信息
      const cachedUser = this.getUserInfo();
      if (cachedUser) {
        console.log('🚫 getCurrentUser: 请求被阻止，返回缓存用户信息');
        return cachedUser;
      }
      // 如果没有缓存，抛出错误
      throw new Error('用户信息请求进行中，请稍后重试');
    }

    try {
      console.log('📡 getCurrentUser: 发送请求');
      const response = await api.get<UserProfile>('/v1/auth/me');
      const user = response.data.data;

      // 更新本地存储的用户信息
      this.saveUserInfo(user);

      return user;
    } catch (error: any) {
      throw error;
    } finally {
      requestGuard.completeRequest('getCurrentUser');
    }
  }

  /**
   * 检查令牌有效性 - 使用requestGuard防止重复请求
   */
  async checkToken(): Promise<boolean> {
    // 使用requestGuard防止重复请求
    if (!requestGuard.canRequest('checkToken')) {
      console.log('🚫 checkToken: 请求被阻止，返回true（假设token有效）');
      return true; // 假设token有效，避免重复检查
    }

    try {
      console.log('📡 checkToken: 发送请求');
      await api.get('/v1/auth/check-token');
      return true;
    } catch (error) {
      return false;
    } finally {
      requestGuard.completeRequest('checkToken');
    }
  }

  /**
   * 保存认证数据到本地存储
   */
  private saveAuthData(authData: LoginResponse): void {
    const token: Token = {
      access_token: authData.access_token,
      refresh_token: authData.refresh_token,
      token_type: authData.token_type,
      expires_in: authData.expires_in,
      expires_at: Date.now() + authData.expires_in * 1000
    };

    storage.set(AUTH_STORAGE_KEYS.TOKEN, token);
    storage.set(AUTH_STORAGE_KEYS.USER_INFO, authData.user);
    storage.set(AUTH_STORAGE_KEYS.PERMISSIONS, authData.user.permissions);
  }

  /**
   * 更新令牌信息
   */
  private updateToken(token: Token): void {
    storage.set(AUTH_STORAGE_KEYS.TOKEN, token);
  }

  /**
   * 保存用户信息
   */
  private saveUserInfo(user: UserProfile): void {
    storage.set(AUTH_STORAGE_KEYS.USER_INFO, user);
    storage.set(AUTH_STORAGE_KEYS.PERMISSIONS, user.permissions);
  }

  /**
   * 清除认证数据
   */
  private clearAuthData(): void {
    storage.remove(AUTH_STORAGE_KEYS.TOKEN);
    storage.remove(AUTH_STORAGE_KEYS.USER_INFO);
    storage.remove(AUTH_STORAGE_KEYS.PERMISSIONS);
    storage.remove(AUTH_STORAGE_KEYS.REMEMBER_ME);
  }

  /**
   * 获取访问令牌
   */
  getAccessToken(): string | null {
    const token = storage.get<Token>(AUTH_STORAGE_KEYS.TOKEN);
    return token?.access_token || null;
  }

  /**
   * 获取刷新令牌
   */
  getRefreshToken(): string | null {
    const token = storage.get<Token>(AUTH_STORAGE_KEYS.TOKEN);
    return token?.refresh_token || null;
  }

  /**
   * 获取用户信息
   */
  getUserInfo(): UserProfile | null {
    return storage.get<UserProfile>(AUTH_STORAGE_KEYS.USER_INFO);
  }

  /**
   * 获取用户权限
   */
  getUserPermissions(): string[] {
    return storage.get<string[]>(AUTH_STORAGE_KEYS.PERMISSIONS) || [];
  }

  /**
   * 检查是否已认证
   */
  isAuthenticated(): boolean {
    const token = storage.get<Token>(AUTH_STORAGE_KEYS.TOKEN);
    if (!token) return false;
    
    // 检查令牌是否过期
    return Date.now() < token.expires_at;
  }

  /**
   * 检查令牌是否即将过期（5分钟内）
   */
  isTokenExpiringSoon(): boolean {
    const token = storage.get<Token>(AUTH_STORAGE_KEYS.TOKEN);
    if (!token) return false;
    
    const fiveMinutes = 5 * 60 * 1000;
    return Date.now() + fiveMinutes >= token.expires_at;
  }

  /**
   * 检查用户是否拥有指定权限
   */
  hasPermission(permission: string): boolean {
    const user = this.getUserInfo();
    if (!user) return false;

    // 类型检查：确保permission是字符串
    if (typeof permission !== 'string') {
      console.warn('hasPermission: permission参数必须是字符串', permission);
      return false;
    }

    // 超级用户拥有所有权限
    if (user.is_superuser) return true;

    // 处理权限数组格式（可能是字符串数组或对象数组）
    const userPermissions = user.permissions?.map(p =>
      typeof p === 'string' ? p : p.name
    ) || [];

    // 基础权限检查
    if (userPermissions.includes(permission)) return true;

    // 权限继承检查（简化版）
    // system.admin 包含所有权限
    if (userPermissions.includes('system.admin')) return true;

    // user.admin 包含用户和角色相关权限
    if (userPermissions.includes('user.admin')) {
      if (permission.startsWith('user.') || permission.startsWith('role.') || permission.startsWith('permission.')) {
        return true;
      }
    }

    // data.admin 包含数据相关权限
    if (userPermissions.includes('data.admin')) {
      if (permission.startsWith('lineage.') || permission.startsWith('task.')) {
        return true;
      }
    }

    // 管理权限包含相关的基础权限
    const resourceAction = permission.split('.');
    if (resourceAction.length === 2) {
      const [resource, action] = resourceAction;
      const managePermission = `${resource}.manage`;
      if (userPermissions.includes(managePermission)) {
        return true;
      }
    }

    return false;
  }

  /**
   * 检查用户是否拥有任一权限
   */
  hasAnyPermission(permissions: string[]): boolean {
    return permissions.some(permission => this.hasPermission(permission));
  }

  /**
   * 检查用户是否拥有所有权限
   */
  hasAllPermissions(permissions: string[]): boolean {
    return permissions.every(permission => this.hasPermission(permission));
  }

  /**
   * 检查用户是否拥有指定角色
   */
  hasRole(roleName: string): boolean {
    const user = this.getUserInfo();
    if (!user) return false;

    // 处理角色数组格式（可能是字符串数组或对象数组）
    const userRoles = user.roles?.map(r =>
      typeof r === 'string' ? r : r.name
    ) || [];

    return userRoles.includes(roleName);
  }

  /**
   * 检查用户是否拥有任一角色
   */
  hasAnyRole(roles: string[]): boolean {
    return roles.some(role => this.hasRole(role));
  }

  /**
   * 获取用户角色
   */
  getUserRoles(): string[] {
    const user = this.getUserInfo();
    if (!user?.roles) return [];

    // 处理角色数组格式（可能是字符串数组或对象数组）
    return user.roles.map(r =>
      typeof r === 'string' ? r : r.name
    );
  }
}

// 导出单例实例
export default new AuthService();
